﻿package kliment.geom.color {
	import kliment.math.Calc;
	
	/**
	* ...
	* @author Kliment
	*/
	public class HSVColor  extends ColorAbstract{
		private const TURN:int = 360;
		private const RADIUS:int = 100;
		
		public var rawH:Number = 0;
		public var rawS:Number = 0;
		public var rawV:Number = 0;
        
		public function HSVColor(host:Color = null) {
			super(host);
		}
		
		public function get h():Number { return rawH * TURN }
		public function get s():Number { return rawS * RADIUS }
		public function get v():Number { return rawV * RADIUS }
		
		public function setValue(h:Number, s:Number, v:Number, update:Boolean = true):void {
			setRawValue(h / TURN, s / RADIUS, v / RADIUS, update);
		}
		
		public function setRawValue(h:Number, s:Number, v:Number, update:Boolean = true):void {
			if (rawH.toFixed(7) == h.toFixed(7) && rawS.toFixed(7) == s.toFixed(7) && rawV.toFixed(7) == v.toFixed(7))
				return;
			rawH = (h + 1000) % 1;
			rawS = Calc.inInterval(MIN_RAW, MAX_RAW, s);
			rawV = Calc.inInterval(MIN_RAW, MAX_RAW, v);
			if (color && update) 
				color.valueChanged(Color.HSV);
		}
		
		public function toString():String {
			return "[HSVColor h=" + h + " s=" + s + " v=" + v + "]";
		}
		
		public function clone():HSVColor {
			var result:HSVColor = new HSVColor();
			result.setRawValue(rawH, rawS, rawV, false);
			return result;
		}
		
		public function toRGB(rgb:RGBColor = null):RGBColor { return converToRGB(this, rgb) }
		static public function converToRGB(hsv:HSVColor, rgb:RGBColor = null):RGBColor {
			if (!rgb) rgb = new RGBColor();
			var rawR:Number;
			var rawG:Number;
			var rawB:Number;
			var rawH:Number = hsv.rawH;
			var rawS:Number = hsv.rawS;
			var rawV:Number = hsv.rawV;
			//rawH = (rawH + 1000) % 1;
			var mode:Number = rawH * 6 >> 0;
			var f:Number = rawH * 6 - mode;
			var p:Number = rawV * (1 - rawS);
			var q:Number = rawV * (1 - rawS * f);
			var t:Number = rawV * (1 - rawS * (1 - f));
			switch(mode){
				case 0: rawR = rawV; rawG = t; rawB = p; break;
				case 1: rawR = q; rawG = rawV; rawB = p; break;
				case 2: rawR = p; rawG = rawV; rawB = t; break;
				case 3: rawR = p; rawG = q; rawB = rawV; break;
				case 4: rawR = t; rawG = p; rawB = rawV; break;
				case 5: rawR = rawV; rawG = p; rawB = q; break;
			}
			rgb.setRawValue(rawR, rawG, rawB, false);		
			return rgb;
		}
	}
}